# -*- coding: utf-8 -*-
"""
In this module we can find some functions used for irc resources.
"""
import re
from util.functions import encode
from ircvars import _ircstring_translation, _abredged_colors

class Features:
	"""
	Get server features in a dict and deliver some of these as methods.
	Choose:
		- chanlimit()	- nicklen()
		- chanlen()		- targmax(...)
		- network()		- topiclen()
	"""
	def __init__(self, d):
		self.d = d

	u"""
	freenode features:
	· CHANTYPES=#								× CHANNELLEN=50
	· EXCEPTS									× TOPICLEN=390
	· INVEX										· ETRACE
	· CHANMODES=eIbq,k,flj,CFLMPQcgimnprstz		· CPRIVMSG
	× CHANLIMIT=#:120							· CNOTICE
	· PREFIX=(ov)@+								· DEAF=D
	· MAXLIST=bqeI:100							· MONITOR=100
	· MODES=4									· FNC
	× NETWORK=freenode							× TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,PRIVMSG:4,NOTICE:4,ACCEPT:,MONITOR:
	· KNOCK										· EXTBAN=$,arx
	· STATUSMSG=@+								· WHOX
	· CALLERID=g								· CLIENTVER=3.0
	· CASEMAPPING=rfc1459						· SAFELIST
	· CHARSET=ascii								· ELIST=CTU
	× NICKLEN=16
	"""
	def chanlimit(self):
		return self.d.get("chanlimit")

	def chanlen(self):
		return self.d.get("channellen")

	def network(self):
		return self.d.get("network")

	def nicklen(self):
		return self.d.get("nicklen")

	def targmax(self, token=""):
		token = token.lower()
		targets = self.d.get("targmax",[])
		d={}
		for t in targets:
			k, v = t.split(":")
			if v is "": v = "true"
			d[k.lower()]=v
		if token and d.has_key(token):
			return d[token]
		else:
			return ", ".join(sorted(["%s: %s" % (k,v) for k, v in d.iteritems()]))

	def topiclen(self):
		return self.d.get("topiclen")

def ircformat(txt):
	for clr in _abredged_colors:
		txt=txt.replace("&%s;" % clr, _abredged_colors[clr])
	return txt

_levels = ("user", "trusty", "support", "tester", "admin", "owner")
skip_shield = _levels[2:]
def has_access(bot, required_level, evt):
	"""one of this: 'user', 'trusty', 'support', 'tester', 'admin'"""
	if required_level not in _levels:
		bot.reply("Unknown level.")
		return False
	if bot.nicks.has_key(evt.source):
		user = bot.nicks[evt.source]
		user_level = bot.accounts.get(user, {"level": None})['level']
		if user_level and _levels.index(user_level) >= _levels.index(required_level):
			return True
		bot.reply(evt, "You have not enough permissions. %s level expected, %s level found", required_level, user_level)
	else:
		bot.reply(evt, "You are not identified with services.")
	return False

def access_idx(bot, required_level, evt):
	"""one of this: 'user', 'trusty', 'support', 'tester', 'admin'"""
	if required_level not in _levels:
		return False
	if bot.nicks.has_key(evt.source):
		user = bot.nicks[evt.source]
		user_level = bot.accounts.get(user, {"level": None})['level']
		if user_level and _levels.index(user_level) >= _levels.index(required_level):
			return True
	else:
		return False

def access_is(bot, required_level, evt):
	if bot.nicks.has_key(evt.source):
		user = bot.nicks[evt.source]
		user_level = bot.accounts.get(user, {"level": None})['level']
		if required_level == user_level:
				return True
		bot.priv_notice("&B;%s&N; level was expected, &B;&r;%s&N; found.", required_level, user_level)
	else:
		bot.priv_notice("You are not identified with services.")
	return False

def check_access(bot, required_level):
	#like function above, but doesn't send msg and only return a bool.
	if bot.nicks.has_key(bot.event.source):
		user = bot.nicks[bot.event.source]
		user_level = bot.accounts.get(user, {"level": None})['level']
		if required_level == user_level:
				return True
	return False

def not_on_channel(bot, channel):
	if bot.event.chan != channel:
		bot.priv_notice("This command is only for $1 channel.", channel)
		return True
	return False


def is_channel(string):
    """Check if a string is a channel name.

    Returns true if the argument is a channel name, otherwise false.
    """
    return string and string[0] in "#&+!"

def has_wildcard(mask, match):
	#check if string has IRC wildcards
	mask = mask.replace('?', '[\\w|\\W]').replace('*', '[\\w|\\W]+')
	regex = re.compile(mask, re.I)
	if regex.match(match) == None: return False
	else: return True

def wildcard_to_regexp(string):
	#Wildcards used in IRC are "?" and "*".
	#Transalte they to a correct regular expression.
	string = string.replace("?",".").replace("*",".*")
	return string

def escape_for_regexp(string):
	#Standardize character as escape caracter in a regular expression
	for char in '^$[].|?+*{}()><-':
		string = string.replace(char, r'\%s' % char)
	return string

def irc_lower(s):
	"""Returns a lowercased string.

	The definition of lowercased comes from the IRC specification (RFC
	1459).
	"""
	s=encode(s)
	return s.translate(_ircstring_translation)

def parse_nick_modes(mode_string):
	"""Parse a nick mode string.

	The function returns a list of lists with three members: sign,
	mode and argument.  The sign is \"+\" or \"-\".  The argument is
	always None.

	Example:

	>>> irclib.parse_nick_modes(\"+ab-c\")
	[['+', 'a', None], ['+', 'b', None], ['-', 'c', None]]
	"""

	return _parse_modes(mode_string, "")

def parse_channel_modes(mode_string):
	"""Parse a channel mode string.

	The function returns a list of lists with three members: sign,
	mode and argument.  The sign is \"+\" or \"-\".  The argument is
	None if mode isn't one of \"b\", \"k\", \"l\", \"v\" or \"o\".

	Example:

	>>> irclib.parse_channel_modes(\"+ab-c foo\")
	[['+', 'a', None], ['+', 'b', 'foo'], ['-', 'c', None]]
	"""

	return _parse_modes(mode_string, "bklvo")

def _parse_modes(mode_string, unary_modes=""):
	"""[Internal]"""
	modes = []
	arg_count = 0

	# State variable.
	sign = ""

	a = mode_string.split()
	if len(a) == 0:
		return []
	else:
		mode_part, args = a[0], a[1:]

	if mode_part[0] not in "+-":
		return []
	for ch in mode_part:
		if ch in "+-":
			sign = ch
		elif ch == " ":
			collecting_arguments = 1
		elif ch in unary_modes:
			if len(args) >= arg_count + 1:
				modes.append([sign, ch, args[arg_count]])
				arg_count = arg_count + 1
			else:
				modes.append([sign, ch, None])
		else:
			modes.append([sign, ch, None])
	return modes

def quiet_nick(nick, users):
	for user in list(users):
		users.remove(user)
		users.append(irc_lower(user))
	if irc_lower(nick) in users:
		if len(nick)==1: return nick
		nick = u"%s·%s" % (nick[0],nick[1:])
	return nick

def _trans(file, string):
	from optimizers import File
	if file == "en": return string
	action = re.search(ur"\x01ACTION (.*)\x01", string)
	if action:
		string = action.group(1)
	try:
		f_lang = File("%s.py" % file, "lang").load()
		variables=vars(f_lang)
		for var in variables.keys():
			if var.startswith("__"): continue
			if variables[var].has_key(string):
				if action:
					string = u"\x01ACTION %s\x01" % variables[var][string]
					return string
				return variables[var][string]
	except ImportError:
		print u"no s'ha pogut carregar el mòdul lang.%s.py" % file
	except:
		print "functions.py exception skipped"
	if action:
		string = u"\x01ACTION %s\x01" % string
	return string

#nick | accounts | nicks | wikiuser | aliases
#nick can have account, and then wikiuser
#nick haven't account, but account contains aliases, and then wikiuser (not recomanded)
#nick haven't account, but a simplelist is available to relate nick and aliases to some account
_aliases = {
	#wiki accounts  #irc nicks
	u"Gomà": ["goma"],
	"Mafoso": ["mafoso","mafoso_espieta","mafoso_clonic"],
	"Barcelona": ["barcelona", "barna"],
	"Jordicollcosta": ["jcc"],
	"VriuBot":  ["vriubot"],
}

def get_account(bot, nick):
	for n in bot.nicks:
		if irc_lower(n) == irc_lower(nick):
			nick = n
			break
	if bot.nicks.has_key(nick) and bot.accounts.has_key(bot.nicks[nick]):
		aliases = dict([(irc_lower(x), x) for x in bot.accounts[bot.nicks[nick]]['aliases']])
		if irc_lower(nick) in aliases:
			nick = bot.accounts[bot.nicks[aliases[irc_lower(nick)]]]['wiki']
	else:
		for account in _aliases:
			if irc_lower(nick) in _aliases[account]:
				nick = account
				break
		for account in bot.accounts():
			if irc_lower(nick) in [irc_lower(x) for x in bot.accounts[account]['aliases']]:
				nick = bot.accounts[account]['wiki']
				break
	return nick

def get_user(cmd, evt):
	user = cmd.opts['u'] or cmd.opts['user'] or cmd.arguments or evt.source
	user = user.replace("::","").replace(r"\-","-")
	if user.endswith(":"): user += evt.source
	return user
